package com.summer.learning.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.summer.commonException.XueChengException;
import com.summer.entity.XcUser;
import com.summer.learning.dto.XcChooseCourseDto;
import com.summer.learning.dto.XcCourseTablesDto;
import com.summer.learning.feignClient.GetPublishCourseById;
import com.summer.learning.feignClient.MediaServiceClient;
import com.summer.learning.mapper.XcChooseCourseMapper;
import com.summer.learning.mapper.XcCourseTablesMapper;
import com.summer.learning.pojo.XcChooseCourse;
import com.summer.learning.pojo.XcCourseTables;
import com.summer.learning.service.LearningService;
import com.summer.model.dto.RestResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;

@Slf4j
@Service
public class LearningServiceImpl implements LearningService {

    @Autowired
    private GetPublishCourseById getPublishCourseById;

    @Autowired
    private XcChooseCourseMapper xcChooseCourseMapper;

    @Autowired
    private XcCourseTablesMapper xcCourseTablesMapper;

    @Autowired
    private MediaServiceClient mediaServiceClient;

    @Transactional
    @Override
    public XcChooseCourseDto  add2MyCourse(String userId,  long courseId) {
        // 1. 判断课程是否收费
        // 远程调用内容管理来查询发布课程
        HashMap coursePublishMap = getCoursePublishMap(courseId);
        if (coursePublishMap == null){
            XueChengException.cast("课程不存在");
        }
        String charge = (String) coursePublishMap.get("charge");
        XcChooseCourse xcChooseCourse = null;
        if ("201000".equals(charge)){
        // 2. 免费：将课程添加到选课记录表（选课成功）、我的课程表
            xcChooseCourse = add2ChooseCourse(userId, coursePublishMap, charge);
            XcCourseTables xcCourseTables = add2CourseTable(xcChooseCourse);
        }else {
        // 3. 收费：将发布课程添加到选课记录表（待支付）, todo......
            xcChooseCourse = add2ChooseCourse(userId, coursePublishMap, charge);
        }
        XcChooseCourseDto xcCourseTablesDto = new XcChooseCourseDto();
        BeanUtils.copyProperties(xcChooseCourse, xcCourseTablesDto);
        xcCourseTablesDto.setIsCanLearn(getLeanringStatus(userId, courseId).getIsCanLearn());
        return xcCourseTablesDto;
    }

    private HashMap getCoursePublishMap(long courseId) {
        String coursePublish = getPublishCourseById.getById(courseId);
        if (coursePublish == null){
           return null;
        }
        // 将json转为map
        return JSON.parseObject(coursePublish, HashMap.class);
    }

    // [
    //      {"code":"702001","desc":"正常学习"},
    //      {"code":"702002","desc":"没有选课或选课后没有支付"},
    //      {"code":"702003","desc":"已过期需要申请续期或重新支付"}
    // ]
    @Override
    public XcCourseTablesDto getLeanringStatus(String userId, Long courseId) {
        //查询我的课程表
        XcCourseTables xcCourseTables = getXcCourseTables(userId, courseId);

        // 课程表有记录："code":"702002","desc":"没有选课或选课后没有支付"
        if(xcCourseTables==null){
            XcCourseTablesDto xcCourseTablesDto = new XcCourseTablesDto();
            //没有选课或选课后没有支付
            xcCourseTablesDto.setIsCanLearn("702002");
            return xcCourseTablesDto;
        }
        XcCourseTablesDto xcCourseTablesDto = new XcCourseTablesDto();
        BeanUtils.copyProperties(xcCourseTables,xcCourseTablesDto);
        //是否过期,true过期，false未过期
        boolean isExpires = xcCourseTables.getValidtimeEnd().isBefore(LocalDateTime.now());

        // 课程表无记录：是否过期 ？702003 : 701001
        if(!isExpires){
            //正常学习
            xcCourseTablesDto.setIsCanLearn("702001");
            return xcCourseTablesDto;

        }else{
            //已过期
            xcCourseTablesDto.setIsCanLearn("702003");
            return xcCourseTablesDto;
        }
    }

    // 获取视频地址接口
    @Override
    public RestResponse<String> getVideo(String userId, Long courseId, Long teachplanId, String mediaId) {
        // 1. 查询课程信息
        HashMap coursePublishMap = getCoursePublishMap(courseId);
        if (coursePublishMap == null){
            XueChengException.cast("课程不存在");
        }

        //2. 校验学习资格
        //2.1 如果登录
        if(!StringUtils.isEmpty(userId)){
            //判断是否选课，根据选课情况判断学习资格
            XcCourseTablesDto xcCourseTablesDto = getLeanringStatus(userId, courseId);
            //学习资格状态 [{"code":"702001","desc":"正常学习"},{"code":"702002","desc":"没有选课或选课后没有支付"},{"code":"702003","desc":"已过期需要申请续期或重新支付"}]
            String learnStatus = xcCourseTablesDto.getIsCanLearn();
            if(learnStatus.equals("702001")){
                return mediaServiceClient.getPlayUrlByMediaId(mediaId);
            }else if(learnStatus.equals("702003")){
                RestResponse.validfail("您的选课已过期需要申请续期或重新支付");
            }
        }
        //2.2 未登录或未选课判断是否收费
        String charge = (String) coursePublishMap.get("charge");
        if(charge.equals("201000")){//免费可以正常学习
            return mediaServiceClient.getPlayUrlByMediaId(mediaId);
        }
        return RestResponse.validfail("请购买课程后继续学习");
    }

    /**
     * 查询课程表中是否存在当前课程
     * @param userId userId
     * @param courseId  courseId
     * @return 返回一门课
     */
    private XcCourseTables getXcCourseTables(String userId, Long courseId) {
        return xcCourseTablesMapper.selectOne(
                new LambdaQueryWrapper<XcCourseTables>()
                        .eq(XcCourseTables::getCourseId,courseId)
                        .eq(XcCourseTables::getUserId, userId));
    }

    /**
     * 添加课程信息到我的课程表中
     * @param xcChooseCourse 课程信息
     */
    private XcCourseTables add2CourseTable(XcChooseCourse xcChooseCourse) {
        // 选课未完成或课程已过期就不能添加到课程表中
        boolean isExpire = xcChooseCourse.getValidtimeEnd().isBefore(LocalDateTime.now());
        if (!xcChooseCourse.getStatus().equals("701001") || isExpire){
            log.error("选课未完成");
            XueChengException.cast("选课失败，请重试");
        }

        // 若课程已存在则抛出异常
        XcCourseTables xcCourseTables = getXcCourseTables(xcChooseCourse.getUserId(), xcChooseCourse.getCourseId());
        if (xcCourseTables != null){
            XueChengException.cast("课程已存在");
        }
        xcCourseTables = new XcCourseTables();
        xcCourseTables.setChooseCourseId(xcChooseCourse.getId());
        xcCourseTables.setUserId(xcChooseCourse.getUserId());
        xcCourseTables.setCourseId(xcChooseCourse.getCourseId());
        xcCourseTables.setCompanyId(xcChooseCourse.getCompanyId());
        xcCourseTables.setCourseName(xcChooseCourse.getCourseName());
        xcCourseTables.setCourseType(xcChooseCourse.getOrderType());
        xcCourseTables.setCreateDate(LocalDateTime.now());
        xcCourseTables.setValidtimeStart(LocalDateTime.now());
        xcCourseTables.setValidtimeEnd(LocalDateTime.now().plusDays(xcChooseCourse.getValidDays()));
        xcCourseTables.setUpdateDate(LocalDateTime.now());
        xcCourseTables.setRemarks(xcChooseCourse.getRemarks());
        xcCourseTablesMapper.insert(xcCourseTables);
        return xcCourseTables;
    }

    /**
     * 添加课程信息到选课记录表（包括免费、收费）
     * @param userId 用户id
     * @param coursePublishMap 课程信息
     * @return 返回选课记录dto，方便添加到课程表时调用
     */
    private XcChooseCourse add2ChooseCourse(String userId, HashMap<String, String> coursePublishMap, String charge) {
        // 1 若选课记录表中存在记录且已完成选课则直接赋值（防止重复选课）
        long courseId = Long.parseLong(String.valueOf(coursePublishMap.get("id")));
        List<XcChooseCourse> xcChooseCourseList = xcChooseCourseMapper.selectList(
                new LambdaQueryWrapper<XcChooseCourse>()
                        .eq(XcChooseCourse::getCourseId, courseId)
                        .eq(XcChooseCourse::getUserId, userId)
                        .eq(XcChooseCourse::getStatus, "701001"));
        if (xcChooseCourseList.size() > 0){
            return xcChooseCourseList.get(0);
        }
        // 2 不存在则封装XcChooseCourse
        XcChooseCourse xcChooseCourse = new XcChooseCourse();
        xcChooseCourse.setCourseId(courseId);
        xcChooseCourse.setCourseName(coursePublishMap.get("name"));
        xcChooseCourse.setUserId(userId);
        xcChooseCourse.setCompanyId(Long.parseLong(String.valueOf(coursePublishMap.get("companyId"))));
        xcChooseCourse.setCreateDate(LocalDateTime.now());
        Object price = coursePublishMap.get("price");
        xcChooseCourse.setCoursePrice(((BigDecimal) price).floatValue());
        // 免费：已选；收费：待支付
        if ("201000".equals(charge)){
            xcChooseCourse.setStatus("701001");
        } else{
            xcChooseCourse.setStatus("701002");
        }
        xcChooseCourse.setOrderType(charge);
        xcChooseCourse.setValidtimeStart(LocalDateTime.now());
        // 有效期默认1年
        Object validDays = coursePublishMap.get("validDays");
        if (!StringUtils.isEmpty(validDays)){
            xcChooseCourse.setValidDays((Integer) validDays);
            xcChooseCourse.setValidtimeEnd(LocalDateTime.now().plusDays((Integer) validDays));
        } else {
            xcChooseCourse.setValidDays(365);
            xcChooseCourse.setValidtimeEnd(LocalDateTime.now().plusYears(1));
        }
        xcChooseCourse.setRemarks(coursePublishMap.getOrDefault("remark", ""));
        int insert = xcChooseCourseMapper.insert(xcChooseCourse);
        if (insert<=0){
            XueChengException.cast("添加免费课程到选课记录表失败");
        }
        return xcChooseCourse;
    }
}
